﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.Scripting.Ast;
using Scala.Compiler.Types;
using Scala.Compiler.Binding;

namespace Scala.Compiler.Ast
{

    public enum ParameterKind
    {
        Normal,
        Function,
        List
    }

    public class Parameter:Tree
    {
        private readonly string _name;
        private string _returnType;
        protected readonly ParameterKind _kind;
        protected Expression _defaultValue;

        public Parameter(string name) : this(name, ParameterKind.Normal) { }

        public Parameter(string name, ParameterKind kind)
        {
            _name = name;
            _kind = kind;
        }

        /// <summary>
        /// Parameter name
        /// </summary>
        public string Name { get { return _name; } }

        public ScalaVariable ScalaVariable { get; set; }

        public Expression DefaultValue
        {
            get { return _defaultValue; }
            set { _defaultValue = value; }
        }

        public bool IsList { get { return _kind == ParameterKind.List; } }
        public bool IsFunction { get { return _kind == ParameterKind.Function; } }

        public string ReturnType
        {
            get
            {
                if (!IsFunction) return TypeName;
                return _returnType;
            }
            set { _returnType = value; }
        }

        internal ParameterKind Kind { get { return _kind; } }

        public override void Walk(ScalaWalker walker)
        {
            if (walker.Walk(this))
            {
                if (_defaultValue != null) { _defaultValue.Walk(walker); }
            }
            walker.PostWalk(this);
        }

        public override Microsoft.Scripting.Ast.Expression Reduce()
        {
            Type t;
            ScalaVariable variable;
            if(!InternalTypes.GetType(TypeName,Scope,out t))
            {
                throw new Exception(String.Format("Undefined Type {0} of the Parameter {1} in the Scope {2}",TypeName,Name,Scope.Name));
            }
            Scope.TryGetAnyVariable(Name, out variable);
            variable.ParamExpression = Expression.Variable(t, Name);

            return Expression.Empty();
        }
    }
}
